// Copyright (C) ustc9703
// All rights reserved.
// 
// Author : Jiang Li
// Date   : 2004-12-21

#include "stdafx.h"
#include "async_login.h"
#include "msvr_server.h"
#include "msvr_user.h"
#include <common/svr_base/db_utility.h>
#include <common/svr_base/svr_showinfo.h>
#include <common/netmsg/netmsg.h>
#include <common/svr_base/dbmsg_base.h>

namespace JoyServer
{

// class CJoyAsyncLogin

CJoyAsyncLogin::CJoyAsyncLogin(CJoyMainUser* pUser)
    : CJoyUserAsyncObject(pUser)
{
}

CJoyAsyncLogin::~CJoyAsyncLogin()
{
}

UINT CJoyAsyncLogin::DoLogin()
{

    CJoyMainUser* pUser = (CJoyMainUser*)m_user;
    CJoyMainServer* pServer = pUser->GetServer();

    // update online user table.
    {
        // check for exit.
        CheckUserStatus();

        // open online user database session.
        CJoyDbSession onlineUserSess;
        if(!JoyOpenDbSession(pServer, onlineUserSess,
            pServer->m_dbSetOUser.GetSource(pUser->m_userId)))
        {
            return JoyMessage::Error_Failed;
        }

        // check for exit.
        CheckUserStatus();

        // try login command.
        CJoyDbCommand cmdLogin;
        UINT tempId = pUser->GetTempId();
        if(!JoyInvokeCommand(pServer, onlineUserSess, cmdLogin,
            L"battle_main_user_login",
            pUser->m_userId,
            pUser->m_password,
            pServer->m_serverId,
            pUser->m_room->m_roomId,
            tempId))
        {
            return JoyMessage::Error_Failed;
        }

        if(!HasMoreRow(cmdLogin.MoveNext()))
        {
            return JoyMessage::Error_NotLogin;
        }

        cmdLogin.GetValue("nickname", pUser->m_nickname);
        cmdLogin.GetValue("sex", pUser->m_sex);
        cmdLogin.GetValue("troop", pUser->m_troop);

        UINT origMainServer = 0;
        cmdLogin.GetValue("main_server", origMainServer);
        if(origMainServer != 0)
        {
            UINT origTempId = 0;
            cmdLogin.GetValue("temp_main_id", origTempId);
            pServer->m_dbMsgHandler->KickUserMainTemp(
                pUser->m_userId, JoyMessage::Error_AlreadyOnline, origMainServer, origTempId);

            return JoyMessage::Error_AlreadyOnline;
        }
    }

    // read user troop
    {
        // check for exit.
        CheckUserStatus();

        CJoyDbSession userSess;
        if(!JoyOpenDbSession(pServer, userSess, pServer->m_dbUser))
        {
            return JoyMessage::Error_Failed;
        }

        // check for exit.
        CheckUserStatus();

        CJoyDbCommand readTroop;
        if(!JoyInvokeCommand(pServer, userSess, readTroop,
            L"select_troop", pUser->m_troop))
        {
            return JoyMessage::Error_Failed;
        }

        if(!HasMoreRow(readTroop.MoveNext()))
        {
            pServer->m_showInfo->QueueTimeColorText(InfoColor_Error,
                "cannot get troop by id [%d]. user <%d> login failed.\n",
                pUser->m_troop, pUser->m_userId);
            return JoyMessage::Error_Failed;
        }
        readTroop.GetBoolean("banned",              pUser->m_troop_banned);
        readTroop.GetBoolean("chat",                pUser->m_troop_chat);
        readTroop.GetBoolean("kick",                pUser->m_troop_kickUser);
        readTroop.GetBoolean("mute",                pUser->m_troop_muteUser);
        readTroop.GetBoolean("command",             pUser->m_troop_command);
        readTroop.GetBoolean("block_user",          pUser->m_troop_blockUser);
        readTroop.GetBoolean("change_room_pass",    pUser->m_troop_changeRoomPass);
        readTroop.GetBoolean("close_room",          pUser->m_troop_closeRoom);
        readTroop.GetBoolean("note",                pUser->m_troop_sendNote);
    }

    pUser->m_roomData->Load(pUser);
    return JoyMessage::Error_Ok;
}

void CJoyAsyncLogin::OnExecute()
{
    UINT err = JoyMessage::Error_Ok;
    try
    {
        err = DoLogin();
    }
    catch(EUserExit)
    {
        
    }

    CJoyMainUser* pUser = (CJoyMainUser*)m_user;

    if(err != JoyMessage::Error_Ok)
    {
        pUser->Kick(err);
        return;
    }

    CJoyMainServer* pServer = pUser->GetServer();
    UINT count = (UINT)pServer->m_userSets.GetCount();
    if(count == 0)
    {
        pUser->Kick(JoyMessage::Error_UserMax);
        return;
    }

    // check user attibutes.
    if(!pUser->IsAdminTroop())
    {
        if(pUser->m_credit < (int)pUser->m_room->m_userCreditMin)
        {
            pUser->Kick(JoyMessage::Error_CreditLow);
            return;
        }
    }

    // enter room
    if(!pUser->m_room->UserEnter(pUser))
    {
        pUser->Kick();
    }
}

// class CJoyAsyncLogout

CJoyAsyncLogout::CJoyAsyncLogout(CJoyMainUser* pUser)
    : CJoyUserAsyncObject(pUser)
{
}

CJoyAsyncLogout::~CJoyAsyncLogout()
{
}

void CJoyAsyncLogout::OnExecute()
{
    CJoyMainUser* pUser = (CJoyMainUser*)m_user;
    CJoyMainServer* pServer = pUser->GetServer();

    // open onlineuserdb session.
    CJoyDbSource& dbOUser = pServer->m_dbSetOUser.GetSource(pUser->m_userId);
    CJoyDbSession sessOUser;
    if(!JoyOpenDbSession(pServer, sessOUser, dbOUser))
    {
        return;
    }

    // remove user record from online table.
    CJoyDbCommand removeCommand;
    UINT tempId = pUser->GetTempId(); // temporary login id.
    if(!JoyInvokeCommand(pServer, sessOUser, removeCommand,
        L"battle_main_user_logout",
        pUser->m_userId,
        pServer->m_serverId,
        tempId))
    {
        return;
    }

}

} // namespace JoyServer